home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / sat / msat09.tgz / XWEBER.C < prev   
Text File  |  1994-09-17  |  13KB  |  651 lines

  1. /*
  2.  *   Copyright 1992, 1993, 1994 John Melton (G0ORX/N6LYT)
  3.  *              All Rights Reserved
  4.  *
  5.  *   This program is free software; you can redistribute it and/or modify
  6.  *   it under the terms of the GNU General Public License as published by
  7.  *   the Free Software Foundation; either version 1, or (at your option)
  8.  *   any later version.
  9.  *
  10.  *   This program is distributed in the hope that it will be useful,
  11.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *   GNU General Public License for more details.
  14.  *
  15.  *   You should have received a copy of the GNU General Public License
  16.  *   along with this program; if not, write to the Free Software
  17.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20.  
  21. /*
  22.     xweber.c
  23.  
  24.     Weber Photo Image Capture
  25.  
  26.     John Melton
  27.     G0ORX, N6LYT
  28.  
  29.     4 Charlwoods Close
  30.     Copthorne
  31.     West Sussex
  32.     RH10 3QZ
  33.     England
  34.  
  35.     INTERNET:    g0orx@amsat.org
  36.             n6lyt@amsat.org
  37.             john@images.demon.co.uk
  38.             J.D.Melton@slh0613.icl.wins.co.uk
  39.  
  40.     History:
  41.     -------
  42.  
  43.     0.1    Initial version.
  44.     0.2    Changed code to update line in file.
  45.     0.3    Experimental SPECTRUM capture.
  46.     0.4    Converted to Xaw.
  47. */
  48.  
  49.  
  50. /*
  51. #define DEBUG
  52. #define USEDATA
  53. #define SAVEDATA
  54. */
  55.  
  56. #define VERSION_STRING "(version 0.4 by g0orx/n6lyt/g4klx)"
  57.  
  58. #include <X11/Intrinsic.h>
  59. #include <X11/StringDefs.h>
  60. #include <X11/Shell.h>
  61. #include <X11/Xaw/Cardinals.h>
  62. #include <X11/Xaw/Form.h>
  63. #include <X11/Xaw/Text.h>
  64. #include <X11/Xaw/AsciiText.h>
  65. #include <X11/Xaw/Command.h>
  66.  
  67. #include <sys/types.h>
  68. #include <sys/socket.h>
  69.  
  70. #include <netinet/in.h>
  71. #include <linux/ax25.h>
  72.  
  73. #include <fcntl.h>
  74. #include <unistd.h>
  75. #include <stdio.h>
  76. #include <stdlib.h>
  77. #include <signal.h>
  78. #include <termios.h>
  79.  
  80. #include "weber.h"
  81.  
  82. Display *dpy;
  83.  
  84. XtAppContext app_context;
  85.  
  86. typedef struct
  87. {
  88.     XFontStruct *button_font, *text_font;
  89. }
  90. Resources;
  91.  
  92. Resources  resources;
  93.  
  94. Widget toplevel, compwindow, quitbutton, datawindow;
  95.  
  96. char writebuf[100];
  97.  
  98. XtResource resource_list[] =
  99. {
  100.     {"buttonFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  101.         XtOffsetOf(Resources, button_font), XtRString, XtDefaultFont},
  102.     {"textFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  103.         XtOffsetOf(Resources, text_font), XtRString, XtDefaultFont}
  104. };
  105.  
  106. Arg shell_args[] =
  107. {
  108.     {XtNtitle,        (XtArgVal)NULL}
  109. };
  110.  
  111. Arg form_args[] =
  112. {
  113.     {XtNdefaultDistance,    (XtArgVal)0}
  114. };
  115.  
  116. Arg button_args[] =
  117. {
  118.     {XtNcallback,        (XtArgVal)NULL},
  119.     {XtNlabel,        (XtArgVal)NULL},
  120.     {XtNfromHoriz,        (XtArgVal)NULL},
  121.     {XtNfont,        (XtArgVal)NULL},
  122.     {XtNresize,        (XtArgVal)False},
  123.     {XtNvertDistance,    (XtArgVal)6},
  124.     {XtNhorizDistance,    (XtArgVal)8},
  125.     {XtNtop,        XtChainTop},
  126.     {XtNbottom,        XtChainTop},
  127.     {XtNleft,        XtChainLeft},
  128.     {XtNright,        XtChainLeft}
  129. };
  130.  
  131. Arg window_args[] =
  132. {
  133.     {XtNfromVert,        (XtArgVal)NULL},
  134.     {XtNbackground,        (XtArgVal)NULL},
  135.     {XtNfont,        (XtArgVal)NULL},
  136.     {XtNcursor,        (XtArgVal)NULL},
  137.     {XtNwidth,        (XtArgVal)600},
  138.     {XtNheight,        (XtArgVal)150},
  139.     {XtNvertDistance,    (XtArgVal)6},
  140.     {XtNhorizDistance,    (XtArgVal)0},
  141.     {XtNtop,        XtChainTop},
  142.     {XtNbottom,        XtChainBottom},
  143.     {XtNleft,        XtChainLeft},
  144.     {XtNright,        XtChainRight},
  145.     {XtNeditType,        XawtextEdit},
  146.     {XtNtype,        XawAsciiString},
  147.     {XtNwrap,        XawtextWrapLine},
  148.     {XtNdisplayNonprinting,    False},
  149.     {XtNdisplayCaret,    False},
  150.     {XtNsensitive,        False}
  151. };
  152.  
  153. char satelliteId[16];
  154.  
  155. int s_raw;
  156. XtInputId infd;
  157.  
  158. #define MAXBUFFER 512
  159. unsigned char buf[MAXBUFFER];
  160. int bufSize;
  161. int bytes;
  162.  
  163. unsigned char expanded[MAXBUFFER*2];
  164. int nExpanded;
  165.  
  166. int imageSeen = 0;
  167. char photoName[256];
  168. unsigned char image[160000];
  169.  
  170. int spectrumSeen = 0;
  171. char spectrumName[256];
  172. unsigned char spectrum[SPECTRUMLENGTH];
  173.  
  174. char text[256];
  175.  
  176. int frames    = 0;
  177. int bytes     = 0;
  178. int crcErrors = 0;
  179.  
  180. int x, y;
  181. int offset;
  182. unsigned char *imagePtr;
  183.  
  184. int fileBytes = 0;
  185.  
  186. void writetext(char *text)
  187. {
  188.     XawTextPosition pos;
  189.     XawTextBlock tt;
  190.  
  191.     return;
  192.  
  193.     tt.firstPos = 0;
  194.     tt.ptr      = text;
  195.     tt.length   = strlen(text);
  196.     tt.format   = FMT8BIT;
  197.  
  198.     pos = XawTextGetInsertionPoint(datawindow);
  199.  
  200.     XawTextReplace(datawindow, pos, pos, &tt);
  201.  
  202.     pos += tt.length;
  203.     XawTextSetInsertionPoint(datawindow, pos);
  204. }
  205.  
  206. /*
  207.  *    Convert a call from the shifted ascii form used in an
  208.  *    AX.25 packet.
  209.  */
  210. int ConvertCall(char *c, char *call)
  211. {
  212.     char *ep = c + 6;
  213.     int ct =0;
  214.  
  215.     while (ct < 6)
  216.     {
  217.         if (((*c >> 1) & 127) == ' ') break;
  218.     
  219.         *call = (*c >> 1) & 127;
  220.         call++;
  221.         ct++;
  222.         c++;
  223.     }
  224.     
  225.     if ((*ep & 0x1E) != 0)
  226.     {    
  227.         *call = '-';
  228.         call++;
  229.         call += sprintf(call, "%d", (int)(((*ep) >> 1) & 0x0F));
  230.     }
  231.  
  232.     *call = '\0';
  233.     
  234.     if (*ep & 1) return 0;
  235.  
  236.     return 1;
  237. }
  238.  
  239. void SetPixel(unsigned char pixel)
  240. {
  241.     *imagePtr = pixel;
  242.     imagePtr += 3;
  243. }
  244.  
  245. /*
  246.  *    process photodata
  247.  */
  248.  
  249. void PhotoData(char *photoId, unsigned char *buffer, int length)
  250. {
  251.     HEADER *p;
  252.     unsigned char *data;
  253.     unsigned char line[WIDTH];
  254.     int i,j,n;
  255.     int f;
  256.  
  257.     strcpy(photoName, photoId);
  258.  
  259.     p = (HEADER *)buffer;
  260.  
  261.     if ((p->flags & 0x03) == 0x03)
  262.     {
  263.         int bytes;
  264.  
  265.         /* ascii text info */
  266.         bytes = length-1;
  267.         if (bytes > 255) bytes = 255;
  268.         sprintf(writebuf, "%s: ascii text (%d)\n", photoId, bytes);
  269.         writetext(writebuf);
  270. #ifdef DEBUG
  271. fprintf(stderr, "%s: ascii text (%d)\n", photoId, bytes);
  272. fflush(stderr);
  273. #endif
  274.         strncpy(text, buffer + 1, bytes);
  275.  
  276.         sprintf(writebuf, "%s\n", buffer + 1);
  277.         writetext(writebuf);
  278. #ifdef DEBUG
  279. fprintf(stderr, "%s\n", buffer + 1);
  280. fflush(stderr);
  281. #endif
  282.  
  283.         /* update the text info in the front of the file */
  284.         if ((f = open(photoName, O_RDWR, 0660)) != -1)
  285.         {
  286.             write(f, text, 256);
  287.         }
  288.         else
  289.         {
  290.             f = creat(photoName, 0660);
  291.             write(f, text, 256);
  292.         }
  293.         
  294.         close(f);
  295.     }
  296.     else
  297.     {
  298.  
  299.         x = (p->flags << 8) | p->xLoc;
  300.         y = p->yLoc / 2;
  301.  
  302.         offset = (y * WIDTH) + 256;
  303.         data   = buffer + sizeof(HEADER);
  304.         imagePtr = line + x;
  305.  
  306.         sprintf(writebuf, "%s: x=%d y=%d\n", photoId, x, y);
  307.         writetext(writebuf);
  308. #ifdef DEBUG
  309. fprintf(stderr, "%s: x=%d y=%d flags=%d offset=%d ptr=%x\n", photoId, x, y, p->flags, offset, (int)imagePtr);
  310. fflush(stderr);
  311. #endif
  312.  
  313.         if ((f = open(photoName, O_RDWR, 0660)) != -1)
  314.         {
  315.             lseek(f, offset, SEEK_SET);
  316.  
  317.             if (read(f, line, WIDTH) <= 0)
  318.                 for (i = 0; i < WIDTH; i++)
  319.                     line[i] = 0;
  320.         }
  321.         else
  322.         {
  323.             for (i = 0; i < WIDTH; i++)
  324.                 line[i] = 0;
  325.  
  326.             f = creat(photoName, 0660);
  327.         }
  328.  
  329.         for (i = 0; i < (length-sizeof(HEADER)); i++)
  330.         {
  331.             if (data[i])
  332.             {
  333.                 *imagePtr = data[i];
  334.                 imagePtr += 3;
  335.             }
  336.             else
  337.             {
  338.                 i++;
  339.                 n = data[i++];
  340.                 for (j = 0; j < n; j++)
  341.                 {
  342.                     *imagePtr = data[i];
  343.                     imagePtr += 3;
  344.                 }
  345.             }
  346.         }
  347. #ifdef DEBUG
  348. fprintf(stderr, "updating image file\n");
  349. fflush(stderr);
  350. #endif
  351.         lseek(f, offset, SEEK_SET);
  352.         write(f, line, WIDTH);
  353.         close(f);
  354.     }
  355. }
  356.  
  357. void SpectrumData(char *spectrumId, unsigned char *buffer, int length)
  358. {
  359.     int f;
  360.     int start, end;
  361.     int i;
  362.  
  363.     if (spectrumSeen == 0)
  364.     {
  365.         strcpy(spectrumName, spectrumId);
  366.  
  367.         if ((f = open(spectrumName, O_RDWR, 0660)) != -1)
  368.         {
  369.             read(f, text, 256);
  370.             read(f, spectrum, SPECTRUMLENGTH);
  371.             close(f);
  372.         }
  373.         
  374.         spectrumSeen = 1;
  375.     }
  376.  
  377.     if (buffer[0] == 0x0D && buffer[1] == 0x0A)
  378.     {
  379.         int bytes;
  380.  
  381.         /* ascii text info */
  382.         bytes = length;
  383.         if (bytes > 255) bytes = 255;
  384.  
  385.         sprintf(writebuf, "%s: ascii text (%d)\n", spectrumId, bytes);
  386.         writetext(writebuf);
  387. #ifdef DEBUG
  388. fprintf(stderr, "%s: ascii text (%d)\n", spectrumId, bytes);
  389. #endif
  390.         strncpy(text, buffer, bytes);
  391.  
  392.         sprintf(writebuf, "%s\n", buffer);
  393.         writetext(writebuf);
  394. #ifdef DEBUG
  395. fprintf(stderr, "%s\n", buffer);
  396. #endif
  397.     }
  398.     else
  399.     {
  400.         start = buffer[0] * 128;
  401.         end   = buffer[1] * 128;
  402.         sprintf(writebuf, "%s: start=%d end=%d\n", spectrumId, start, end );
  403.         writetext(writebuf);
  404. #ifdef DEBUG
  405. fprintf(stderr, "%s: start=%d end=%d\n", spectrumId, start, end);
  406. #endif
  407.         for (i = 0; i < 128; i++)
  408.             spectrum[i] = buffer[i + 2];
  409.     }
  410.  
  411. #ifdef DEBUG
  412. fprintf(stderr, "updating spectrum file\n");
  413. #endif
  414.     /* update the image file */
  415. /*
  416.     f = creat(spectrumName, 0660);
  417.     write(f, text, 256);
  418.     write(f, spectrum, SPECTRUMLENGTH);
  419.     close(f);
  420. */
  421.  
  422. #ifdef DEBUG
  423. fprintf(stderr, "exiting\n");
  424. #endif
  425. }
  426.  
  427. /*
  428.  *    decode a received frame.
  429.  */
  430. void ProcessFrame(void)
  431. {
  432.     int n;
  433.     int via;
  434.     unsigned char protocol;
  435.     char toCall[10];
  436.     char fromCall[10];
  437.     char viaCall[10];
  438.  
  439.     frames++;
  440.     bytes+=bufSize;
  441.  
  442.  
  443.     /* check that frame is a kiss data frame */
  444.     /* ignore control frames - should not happen */
  445.     n = 0;
  446.     if ((buf[n] & 0x0F) == 0)
  447.     {
  448.         n++;
  449.  
  450.         /* decode the to/from address */
  451.         /* dont expect via address, but saves last if any */
  452.         via = ConvertCall(buf + n, toCall);
  453.         n+=7;
  454.         
  455.         via = ConvertCall(buf + n, fromCall);
  456.         n+=7;
  457.         
  458.         while (via)
  459.         {
  460.             via = ConvertCall(buf + n, viaCall);
  461.             n += 7;
  462.         }
  463.  
  464.         /* check for a UI frame */
  465.         if ((buf[n] & 0xEF) == 0003)
  466.         {
  467.  
  468.             n++;
  469.             protocol = buf[n++];
  470.  
  471.             /* see if this is a photo frame */
  472.             if (strncmp(toCall, "PHOTO", 5) == 0)
  473.             {
  474.                 PhotoData(toCall, buf + n, bufSize - n);
  475.             }
  476.             else if (strncmp(toCall, "SPECT", 5) == 0)
  477.             {
  478.                 SpectrumData(toCall, buf + n, bufSize - n);
  479.             }
  480.             else if (strcmp(toCall, "PBLIST") == 0 ||
  481.                  strcmp(toCall, "BBSTAT") == 0 ||
  482.                  strcmp(toCall, "QST")    == 0 ||
  483.                  strcmp(toCall, "AMSAT")  == 0 ||
  484.                  strcmp(toCall, "LSTAT")  == 0 ||
  485.                  strcmp(toCall, "BSTAT")  == 0 ||
  486.                  strcmp(toCall, "HITVER") == 0 ||
  487.                  strcmp(toCall, "TIME-1") == 0)
  488.             {
  489.                 buf[bufSize] = '\0';
  490.                 sprintf(writebuf, "%s\n", buf + n);
  491.                 writetext(writebuf);
  492. #ifdef DEBUG
  493. fprintf(stderr, "%s\n", buf + n);
  494. fflush(stderr);
  495. #endif
  496.             }
  497.         }
  498.     }
  499. }
  500.  
  501. /*
  502.  *    callback function when a frame is received.
  503.  */
  504. void GetFrame(XtPointer closure, int *s, XtInputId *Id)
  505. {
  506. #ifdef USEDATA
  507.  
  508.     if (ioctl(s_raw, FIONREAD, &bytes) == -1 || bytes == 0)
  509.     {
  510.         XtRemoveInput(infd);
  511.         return;
  512.     }
  513.  
  514.     if ((bytes = read(s_raw, (char *)&bufSize, sizeof(bufSize))) > 0)
  515.     {
  516.         if ((bufSize = read(s_raw, buf, bufSize)) == -1)
  517.         {
  518.             perror("read 1");
  519.             return;
  520.         }
  521.     }
  522.     else
  523.     {
  524.         perror("read 2");
  525.         return;
  526.     }
  527. #else
  528.     if ((bufSize = recv(s_raw, buf, MAXBUFFER, 0)) == -1)
  529.     {
  530.         perror("recv");
  531.         return;
  532.     }
  533. #endif
  534.  
  535. #ifdef SAVEDATA
  536. {
  537.     int f;
  538.  
  539.     if ((f = open("DATA", O_RDWR | O_CREAT, 0666)) != -1)
  540.     {
  541.         lseek(f, 0L, SEEK_END);
  542.         write(f, (char *)&bufSize, sizeof(bufSize));
  543.         write(f, buf, bufSize);
  544.         close(f);
  545.     }
  546. }
  547. #endif
  548.     fileBytes += bufSize;
  549.     ProcessFrame();
  550. }
  551.  
  552. /*
  553.  *    the user wants to exit this program
  554.  */
  555. void QuitCb(Widget w, XtPointer client_data, XtPointer call_data)
  556. {
  557.     int f;
  558.  
  559.     /* print some stats */
  560.     fprintf(stderr, "\nReceived:\n" );
  561.     fprintf(stderr, "    totalFrames=%d\n", frames);
  562.     fprintf(stderr, "    totalBytes=%d\n", bytes);
  563.     fprintf(stderr, "    crcErrors=%d\n", crcErrors);
  564.     fprintf(stderr, "    fileBytes=%d\n", fileBytes);
  565.  
  566.     /* close the sockets */
  567.     close(s_raw);
  568.  
  569.     if (imageSeen == 1)
  570.     {
  571.         f = creat(photoName, 0660);
  572.         write(f, text, 256);
  573.         write(f, image, WIDTH*HEIGHT);
  574.         close(f);
  575.     }
  576.  
  577.     /* get out */
  578.     XtDestroyApplicationContext(app_context);
  579.  
  580.     exit(0);
  581. }
  582.  
  583. int main(int argc, char **argv)
  584. {
  585.     static XtCallbackRec callback[2];
  586.     char *s, title[80];
  587.  
  588.     if ((s = getenv("SATELLITE")) == NULL)
  589.     {
  590.         printf("SATELLITE environment variable not set.\n");
  591.         return(1);
  592.     }
  593.  
  594.     strcpy(satelliteId, s);
  595.  
  596.     sprintf(title, "xweber:%s %s", satelliteId, VERSION_STRING);
  597.  
  598.     toplevel = XtAppInitialize(&app_context, "Xpb", NULL, 0, &argc, argv,
  599.                 NULL, shell_args, XtNumber(shell_args));
  600.     XtVaSetValues(toplevel, XtNtitle, title, NULL);
  601.  
  602.     dpy  = XtDisplay(toplevel);
  603.  
  604.     XtGetApplicationResources(toplevel, &resources,
  605.                 resource_list, XtNumber(resource_list),
  606.                 NULL, ZERO);
  607.  
  608.     compwindow = XtCreateManagedWidget("appForm", formWidgetClass,
  609.                 toplevel, form_args, XtNumber(form_args));
  610.  
  611.     callback[0].callback = QuitCb;
  612.     callback[0].closure  = toplevel;
  613.     button_args[0].value = (XtArgVal)callback;
  614.     button_args[1].value = (XtArgVal)"Quit";
  615.     button_args[3].value = (XtArgVal)resources.button_font;
  616.     quitbutton = XtCreateManagedWidget("quitButton", commandWidgetClass,
  617.                 compwindow, button_args, XtNumber(button_args));
  618.  
  619.     window_args[0].value = (XtArgVal)quitbutton;
  620.     window_args[1].value = (XtArgVal)WhitePixel(dpy, DefaultScreen(dpy));
  621.     window_args[2].value = (XtArgVal)resources.text_font;
  622.     datawindow = XtCreateManagedWidget("monitorText", asciiTextWidgetClass,
  623.                 compwindow, window_args, XtNumber(window_args));
  624.  
  625. #ifdef USEDATA
  626.     /* open up the data file */
  627.     if ((s_raw = open("DATA", O_RDONLY)) == -1)
  628.     {
  629.         perror("open");
  630.         return(1);
  631.     }
  632. #else
  633.     /* open up the raw socket to receive all packets */
  634.     if ((s_raw = socket(AF_INET, SOCK_PACKET, htons(2))) == -1)
  635.     {
  636.         perror("socket");
  637.         return(1);
  638.     }
  639. #endif
  640.  
  641.     /* we want to be notified whenever a frame is received on the raw socket */
  642.     infd = XtAppAddInput(app_context, s_raw, (XtPointer)XtInputReadMask, GetFrame, NULL);
  643.  
  644.     XtRealizeWidget(toplevel);
  645.  
  646.     XtAppMainLoop(app_context);
  647.     
  648.     return(0);
  649. }
  650.  
  651.